package com.rzjm.api.netty;

/**
 * @创建者：zhouwei
 * @创建时间：2021/5/24
 * @描述：
 */
import cn.hutool.core.util.StrUtil;
import com.rzjm.api.util.DateUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.Date;

/**
 * @author Gjing
 *
 * netty服务端处理器
 **/
@Slf4j
public class NettyServerHandler extends ChannelInboundHandlerAdapter {

    /**
     * 客户端连接会触发
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
//        log.info("新链接加入...");
        System.out.println("新链接加入...");
        ClientSocket clientSocket = new ClientSocket();
        clientSocket.setChannel(ctx.channel());
        clientSocket.setId(ctx.channel().id().asShortText());
        clientSocket.setLastDate(new Date());
        SocketPool.add(clientSocket);
        System.out.println("客户端与服务端连接: : " +  ctx.channel().id().asShortText());
    }

    /**
     * 客户端与服务端 断连时 执行
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception, IOException {
        super.channelInactive(ctx);
        ClientSocket clientSocket = new ClientSocket();
        clientSocket.setChannel(ctx.channel());
        clientSocket.setId(ctx.channel().id().asShortText());
        SocketPool.remove(ctx.channel().id().asShortText());
//        ctx.close(); //断开连接时，必须关闭，否则造成资源浪费，并发量很大情况下可能造成宕机
        System.out.println("客户端与服务端断开连接name: : " +  ctx.channel().id().asShortText());
    }

    /**
     * 客户端发消息会触发
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        try{
            String id = ctx.channel().id().asShortText();
//            System.out.println("session: "+ id);
            if(msg.toString().indexOf("GET / HTTP/1.1") >= 0){
                ctx.channel().flush();
                return;
            }
            String message = msg.toString().replaceAll("\\+","").toUpperCase();

//            System.out.println("接收消息: "+ message);
            System.out.println("接收到消息：" + message +  "       " + DateUtil.getTime());
            ClientSocket clientSocket = SocketPool.getClient(id);
            boolean flag = false;
            if(!message.contains("ME")){
//                System.out.println("信息未接收完毕，没有结尾标识");
                clientSocket.setFlag(1);
                String receiveMsg = clientSocket.getMsg();
                receiveMsg = receiveMsg + message;
                clientSocket.setMsg(receiveMsg);
                flag = true;
            }else{
//                System.out.println("带有结束标志");
                clientSocket.setFlag(0);
                String receiveMsg = clientSocket.getMsg();
                receiveMsg = receiveMsg + message;
                clientSocket.setMsg(receiveMsg);
            }
            String receiveMsg = clientSocket.getMsg();
//            System.out.println("接收后的数据：" + receiveMsg);
            if(!flag){
                MessageModel model = new MessageModel(receiveMsg);
                if(model.getMsgType() != null && model.getMsgType() == 0){
                    String deviceNum = model.getClientNum();
                    //System.out.println("设备编号： " + deviceNum);
                    if(StrUtil.isNotEmpty(deviceNum) && !deviceNum.equals("null")){
                        clientSocket.setTerminalNum(deviceNum);
                    }
                    //判断当前设备是否存在，不存在就添加
                    MessageDecode.getDeviceInfo(deviceNum);
                    String msgRet = MessageDecode.onMessage(model,clientSocket.getDataCode());
                    if(model.getOrder().equals("01") || model.getOrder().equals("02")){
                        System.out.println("SessionId : "+ id +",  返回响应： "  + msgRet + "      " + DateUtil.getTime());
                        ctx.channel().writeAndFlush(msgRet);
                    }else{
                        ctx.channel().flush();
                    }
                }else{
                    ctx.channel().flush();
                }
            }else{
                ctx.channel().flush();
            }
        }catch (Exception e){
            e.printStackTrace();
            ctx.channel().flush();
        }
    }

    /**
     * 从客户端收到新的数据、读取完成时调用
     *
     * @param ctx
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws IOException {
        log.info(" 接收完成 重置 active 时间 " + DateUtil.getTime());
        String id = ctx.channel().id().asShortText();
        ClientSocket clientSocket = SocketPool.getClient(id);
        clientSocket.setLastDate(new Date());
        if(clientSocket.getFlag() == 1){
            System.out.println("信息未接收完毕，等待继续接收");
            ctx.read();
        }else{
            clientSocket.setMsg("");
        }
//        System.out.println("接收完成后的 消息" + clientSocket.getMsg());
        ctx.flush();
    }

    /**
     * 发生异常触发
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
//        ctx.close();
        ctx.flush();
    }

    /**
     * 服务端当read超时, 会调用这个方法
     *
     * @param ctx
     * @param evt
     * @throws Exception
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception, IOException {
        super.userEventTriggered(ctx, evt);
        ctx.close();//超时时断开连接
//        log.info("超时断开连接ip：{}", clientIp);
    }
}
